using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace Toenda.Foundation.Utility {
	/// <summary>
	/// Class ObjectConverter
	/// </summary>
	public static class ObjectConverter {
		///// <summary>
		///// Returns the pointersize of an object
		///// </summary>
		///// <param name="obj"></param>
		///// <returns></returns>
		//public static long SizeOf(object obj) {
		//    RuntimeTypeHandle th = obj.GetType().TypeHandle;
		//    int size = 0;

		//    unsafe {
		//        size = *( *(int**)&th + 1 );
		//    }

		//    return (long)size;
		//}

		/// <summary>
		/// Displays a object with all property on the console
		/// </summary>
		/// <param name="toDisplay"></param>
		public static void DisplayObject(object toDisplay) {
			BindingFlags conOptions = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

			bool isFirst = true;

			foreach(PropertyInfo pi in toDisplay.GetType().GetProperties(conOptions)) {
				try {
					if(pi.CanRead) {
						if(!isFirst) {
							Console.Write(" - ");
						}

						Console.Write(pi.Name);
						Console.Write(": ");
						Console.Write(pi.GetValue(toDisplay, null));
					}
				}
				catch(Exception) {
				}

				isFirst = false;
			}

			Console.Write("\n");
		}

		/// <summary>
		/// Converts the objects.
		/// </summary>
		/// <param name="toConvert">To convert.</param>
		/// <param name="targetObject">The target object.</param>
		/// <param name="conOptions">The con options.</param>
		public static void ConvertObjects(object toConvert, object targetObject, BindingFlags conOptions) {
			foreach(PropertyInfo pi in toConvert.GetType().GetProperties(conOptions)) {
				try {
					if(pi.CanRead) {
						PropertyInfo p = targetObject.GetType().GetProperty(pi.Name, conOptions);

						if(p.CanWrite) {
							p.SetValue(targetObject, pi.GetValue(toConvert, null), null);
						}
					}
				}
				catch(Exception) {
				}
			}

			foreach(FieldInfo fi in toConvert.GetType().GetFields(conOptions)) {
				try {
					FieldInfo f = targetObject.GetType().GetField(fi.Name, conOptions);

					object obj = fi.GetValue(toConvert);

					if(obj != null) {
						if(fi.GetValue(toConvert) != f.GetValue(targetObject)) {
							f.SetValue(targetObject, fi.GetValue(toConvert));
						}
					}
				}
				catch(Exception) {
				}
			}
		}

		/// <summary>
		/// Converts the objects.
		/// </summary>
		/// <param name="toConvert">To convert.</param>
		/// <param name="targetObject">The target object.</param>
		public static void ConvertObjects(object toConvert, object targetObject) {
			ConvertObjects(
				toConvert,
				targetObject,
				BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
			);
		}
	}
}
